#ifndef __MNM_TILE_H
#define __MNM_TILE_H

#pragma once

#include "MNM.h"

namespace MNM
{
	struct Tile
	{
		typedef uint16 Index;
		typedef FixedVec3<uint16, 5> Vertex;
		typedef FixedAABB<uint16, 5> AABB;
	
		struct Triangle
		{
			Index vertex[3];
			uint16 linkCount : 4;
			uint16 firstLink : 12;

			AUTO_STRUCT_INFO
		};

		struct BVNode
		{
			uint16 leaf: 1;
			uint16 offset: 15;

			AABB aabb;

			AUTO_STRUCT_INFO
		};

		struct Link
		{
			uint16 side			: 4;
			uint16 edge			: 2;
			uint16 triangle	: 10;

			enum { OffMesh	= 0xe, };
			enum { Internal = 0xf, };

			AUTO_STRUCT_INFO
		};

		Tile();

		void CopyTriangles(Triangle* triangles, uint16 count);
		void CopyVertices(Vertex* vertices, uint16 count);
		void CopyNodes(BVNode* nodes, uint16 count);
		void CopyLinks(Link* links, uint16 count);

		void AddOffMeshLink(const TriangleID triangleID, const uint16 offMeshIndex);
		void UpdateOffMeshLink(const TriangleID triangleID, const uint16 offMeshIndex);
		void RemoveOffMeshLink(const TriangleID triangleID);

		void Swap(Tile& other);
		void Destroy();

#if MNM_USE_EXPORT_INFORMATION
		void ResetConnectivity(uint8 accessible);
		inline bool IsTriangleAccessible(const uint16 triangleIdx) const 
		{ 
			assert((triangleIdx >= 0) && (triangleIdx < connectivity.triangleCount)); 
			
			return (connectivity.trianglesAccessible[triangleIdx] != 0); 
		}
		inline bool IsTileAccessible() const { return (connectivity.tileAccessible != 0); }

		inline void SetTriangleAccessible(const uint16 triangleIdx)
		{
			assert((triangleIdx >= 0) && (triangleIdx < connectivity.triangleCount)); 

			connectivity.tileAccessible = true;
			connectivity.trianglesAccessible[triangleIdx] = 1; 
		}
#endif

		enum DrawFlags
		{
			DrawTriangles      = BIT(0),
			DrawInternalLinks  = BIT(1),
			DrawExternalLinks  = BIT(2),
			DrawOffMeshLinks   = BIT(3),
			DrawMeshBoundaries = BIT(4),
			DrawBVTree         = BIT(5),
			DrawAccessibility  = BIT(6),

			DrawAll            = ~0ul,
		};

		void Draw(size_t drawFlags, vector3_t origin) const;

		Triangle*	triangles;
		Vertex*		vertices;
		BVNode*		nodes;
		Link*		links;

		uint16 triangleCount;
		uint16 vertexCount;
		uint16 nodeCount;
		uint16 linkCount;
		uint32 hashValue;

#if MNM_USE_EXPORT_INFORMATION

	private:
		struct TileConnectivity
		{
			TileConnectivity()
				: tileAccessible(true)
				, trianglesAccessible(0)
				, triangleCount(0)
			{
			}

			uint8 tileAccessible;
			uint8* trianglesAccessible;
			uint16 triangleCount;
		};

		bool ConsiderExportInformation() const;
		void InitConnectivity(uint16 oldTriangleCount, uint16 newTriangleCount);

		TileConnectivity connectivity;
#endif

	};
}

#endif	// #ifndef __MNM_TILE_H
